using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.Design.Serialization;
using System.CodeDom;
using System.ComponentModel;

namespace Ferpect.GameComponents.Design.Serialization
{
    /// <summary>
    /// This class is used to deserialize a CodeStatementCollection into an
    /// instance of type T. This class is used in cases where T is not a root
    /// component. It also serializes instances using the basic component
    /// serializer.
    /// </summary>
    public class ViewControlCodeDomSerializer<TViewControl, TViewComponent> : CodeDomSerializer
    {
        private readonly string deserializedType = typeof(TViewControl).FullName;
        private readonly string originalType = typeof(TViewComponent).FullName;

        public override object Deserialize(IDesignerSerializationManager manager, object codeObject)
        {
            CodeDomSerializer innerSerializer = (CodeDomSerializer)manager.GetSerializer(typeof(TViewControl), typeof(CodeDomSerializer));
            this.ModifyInstantiation(codeObject as CodeStatementCollection);
            return innerSerializer.Deserialize(manager, codeObject);
        }

        private void ModifyInstantiation(CodeStatementCollection statements)
        {
            if (statements == null) return;

            foreach (CodeStatement statement in statements)
            {
                ModifyAssignment(statement as CodeAssignStatement);
            }
        }

        private void ModifyAssignment(CodeAssignStatement assignment)
        {
            if (assignment == null) return;
            ModifyObjectCreate(assignment.Right as CodeObjectCreateExpression);
        }

        private void ModifyObjectCreate(CodeObjectCreateExpression constructor)
        {
            if (constructor == null) return;
            if (constructor.CreateType.BaseType == this.originalType)
            {
                constructor.CreateType.BaseType = this.deserializedType;
            }
        }

        public override object Serialize(IDesignerSerializationManager manager, object value)
        {
            CodeDomSerializer innerSerializer = (CodeDomSerializer)manager.GetSerializer(typeof(Component), typeof(CodeDomSerializer));
            return innerSerializer.Serialize(manager, value);
        }
    }
}
